package rpc.packet.codec;

import rpc.common.enumeraion.CompressType;
import rpc.common.enumeraion.PackageType;
import rpc.common.enumeraion.SerializerCode;
import rpc.common.extension.ExtensionLoader;
import rpc.intf.CommonSerializer;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import rpc.intf.Compress;
import rpc.intf.impl.compressAlgorithm.GzipCompress;
import rpc.intf.impl.serializer.KryoSerializer;
import rpc.packet.RpcMessage;
import rpc.packet.RpcRequest;

/**
 * 编码器
 * +---------------+---------------+-----------------+--------------+--------------+
 * |  Magic Number |  Package Type | Serializer Type | Compress Type| Data Length |
 * |    4 bytes    |    1 byte    |     1 byte       |   1 byte     |    4 bytes  |
 * +---------------+---------------+-----------------+-------------+--------------+
 * |                          Data Bytes                                          |
 * |                   Length: ${Data Length}                                     |
 * +------------------------------------------------------------------------------+
 */
public class CommonEncoder extends MessageToByteEncoder<RpcMessage> {

    //magic 4 bytes
    private static final int MAGIC_NUMBER = 0xCAFEBABE;

    private final CommonSerializer serializer;

    public CommonEncoder(CommonSerializer serializer) {
        this.serializer = serializer;
    }

    @Override
    protected void encode(ChannelHandlerContext ctx, RpcMessage rpcMessage, ByteBuf out) throws Exception {
        out.writeInt(MAGIC_NUMBER);

        out.writeByte(rpcMessage.getPackageType());
        out.writeByte(rpcMessage.getSerializer());
        out.writeByte(rpcMessage.getCompress());

        //利用加载器 加载一个 单列
        CommonSerializer commonSerializer = ExtensionLoader
                .getExtensionLoader(CommonSerializer.class)
                .getExtension(SerializerCode.getName(rpcMessage.getSerializer()));

        byte[] bodyBytes = commonSerializer.serialize(rpcMessage.getData());

        //利用加载器 加载一个 单列
        Compress compress = ExtensionLoader
                .getExtensionLoader(Compress.class)
                .getExtension(CompressType.getName(rpcMessage.getCompress()));
        bodyBytes = compress.compress(bodyBytes);
        out.writeInt(bodyBytes.length);
        out.writeBytes(bodyBytes);
    }
}
